package com.fy.tt.dao.impl;

import com.fy.sqlparam.map.ISqlMapResult;
import com.fy.sqlparam.map.config.FieldMapMeta;
import com.fy.sqlparam.map.config.MapMetaConfig;
import com.fy.sqlparam.map.config.TableMapMeta;
import com.fy.sqlparam.param.ISqlParameter;
import com.fy.toolhelper.db.BaseDaoImpl;
import com.fy.tt.dao.ITemplateDao;
import com.fy.tt.entity.TemplateEntity;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * Dao的实现, 记得继承{@link BaseDaoImpl}
 * PS: 建议把默认的这个构造方法声明放最下面, 因为它的关注度远没有查询接口高, 这只是习惯, 不强制要求.
 */
public class TemplateDaoImpl extends BaseDaoImpl<TemplateEntity> implements ITemplateDao {

    @Override
    public long getCountByParameter(Connection connection, ISqlParameter parameter) throws Exception {
        // 这是一个SQL模板,
        String sql = "SELECT COUNT(1)" + PH_BASE_TABLES
                + PH_DYNAMIC_JOIN_TABLES
                // 这里加当前接口需要额外关联的表.
                + "WHERE"
                // 这里加当前接口需要的查询条件
                + PH_CONDITIONS;
        // 调用这个formatSql格式化为真正的SQL
        ISqlMapResult mapResult = this.formatSql(sql, parameter);
        return this.getCountBySql(connection, mapResult.getSql(),
                /*, 如果有额外占位参数, 值写在这里 , */mapResult.getArgObjs());
    }

    @Override
    public List<TemplateEntity> listByParameter(Connection connection, ISqlParameter parameter) throws Exception {
        String sql = "SELECT dr.*" + PH_BASE_TABLES
                + PH_DYNAMIC_JOIN_TABLES
                + "WHERE"
                + PH_CONDITIONS
                + PH_ORDER_BY + PH_LIMIT;
        ISqlMapResult mapResult = this.formatSql(sql, parameter);
        return this.listEntitiesBySql(connection, mapResult.getSql(), "te", mapResult.getArgObjs());
    }

    @Override
    public List<Map<String, Object>> listMapsByParameter(Connection connection, ISqlParameter parameter) throws Exception {
        // 查询时指定具体的字段, 查询结果按顺序输出
        String sql = "SELECT dr.id, dr.normal_column" + PH_BASE_TABLES
                + PH_DYNAMIC_JOIN_TABLES
                + "WHERE"
                + PH_CONDITIONS
                + PH_ORDER_BY;
        ISqlMapResult mapResult = this.formatSql(sql, parameter);
        return this.getMapsBySql(connection, new String[]{
                // 保证和语句中的查询顺序一致, 这是查询结果List<Map>中Map的Key
                "id", "normalColumn"
        }, mapResult.getSql(), mapResult.getArgObjs());
    }

    @Override
    public byte[] getAnyByParameter(Connection connection, ISqlParameter parameter) throws Exception {
        String sql = "SELECT te.byte_column " + PH_BASE_TABLES
                + PH_DYNAMIC_JOIN_TABLES
                + "WHERE"
                + PH_CONDITIONS
                + PH_ORDER_BY + PH_LIMIT;
        ISqlMapResult mapResult = this.formatSql(sql, parameter);
        // 主要靠这个IResultSetHandler回调进行ResultSet自定义处理
        // 强烈不建议自己使用Connection查询, 这样代码有冗余且容易没有释放内存.
        return this.executeSql(new IResultSetHandler<byte[]>() {
            @Override
            public byte[] handleResetSet(ResultSet rs) throws Exception {
                while (rs.next()) {
                    return rs.getBytes(1);
                }
                return null;
            }
        }, connection, mapResult.getSql(), mapResult.getArgObjs());
    }

    /**
     * <strong>**重要**: 这些注解配置为模板SQL和配合{@link ISqlParameter}动态查询提供基础信息.</strong>
     * 这些配置有些地方不太好理解, 跟设计有关系, 请体谅.
     */
    @MapMetaConfig(baseTables = "FROM template_entity te",
            queryFields = {
                    @FieldMapMeta(name = "id", value = "te.id"),

                    @FieldMapMeta(name = "otherTableColumn", value = "te_other.id", dependencyNames = "otherTable"),
            },
            joinTables = {
                    @TableMapMeta(name = "otherTable", value = "INNER JOIN template_entity te_other ON te.id = te_other.id"),
                    @TableMapMeta(name = "extendTable", value = "LEFT JOIN template_entity te_left ON te.id = te_left.id"),
            }
    )
    @ExtendConfig(pkFieldMapMeta = "id", values = {
            /**
             * name: 作为IBaseDao.extend的第一个参数, 是该拓展操作对外声明的名称.
             * entityClass: 拓展的实体的类字节码.
             * setFieldName: 设置到当前实体的哪个属性上.
             * tableMapMeta: 需要关联的额外表的@TableMapMeta的名称.
             * dbAlias: 该关联语句中表示该拓展实体的表的表别名.
             * fromFieldName: 最终查询结果以当前实体的哪个属性的值相等于查询出来的拓展实体的属性值为条件设置实体, 可以理解为JOIN的左侧字段对应实体的属性名称.
             * toFieldName: 最终查询结果以当前实体的属性的值相等于查询出来的拓展实体的哪个属性值为条件设置实体, 可以理解为JOIN的右侧字段对应实体的属性名称.
             */
            @Extend(name = "extendAlias", entityClass = TemplateEntity.class, setFieldName = "extendEntity",
                    tableMapMeta = "extendTable", dbAlias = "te_left", fromFieldName = "id",
                    toFieldName = "id")
    })
    public TemplateDaoImpl() throws Exception {
        super();
    }
}
